from __future__ import with_statement
from google.appengine.api import images
from google.appengine.api import files
from google.appengine.ext import webapp
from google.appengine.api import users
from google.appengine.ext import db
import tags
import urllib2
import datetime

'''This module deals with requests to and from the datastore and the cloud storage'''

class Tag(db.Model):
    name = db.StringProperty()
    imageKey = db.StringProperty()

class Photo(db.Model):
    title = db.StringProperty()
    author = db.StringProperty()
    ownerID = db.StringProperty()
    datasize = db.IntegerProperty()
    upload_date = db.DateTimeProperty()
    tags = db.StringProperty()
    
def check_owner(owner_id):
    
    user = users.get_current_user()
    return user.user_id() == owner_id
    
def send_to_storage(imageData, key):
    '''Sends the image to cloud storage, using the image's key as the
    title'''
    
    filename = '/gs/user_images/%s.jpg' %key
    outName = files.gs.create(filename, acl='public-read')
    with files.open(outName, 'a') as outFile:
        outFile.write(imageData)
    files.finalize(outName)
    
def create_thumbnail(imageData, key):
    filename = '/gs/user_images_thumb/%s.jpg' %key
    thumbnail = images.resize(imageData, 120, 160)    
    outName = files.gs.create(filename, acl='public-read')
    with files.open(outName, 'a') as outFile:
        outFile.write(thumbnail)
    files.finalize(outName)
    
def create_photo(title, imageData):
    '''Create a Photo record and return the assigned key'''
    
    user = users.get_current_user()
    photo = Photo()
    photo.author = user.nickname()
    photo.title = title        
    photo.datasize = len(imageData)
    photo.tags = ""
    photo.upload_date = datetime.datetime.now()
    photo.ownerID = user.user_id()
    key = photo.put()
    return key

def get_photo(handler, key):
    '''Use this function to safely retrieve photos from the database'''
    
    try:
        photo = db.get(key)
        if not photo:
            handler.redirect("/error/")
        return photo
    except:
        handler.redirect("/error/")
        
def delete_photo(handler, imageKey):
    '''Deletes the photo with the specified imageKey from the database.
    Image is still stored on google cloud'''
    
    photo = get_photo(handler, imageKey)
    imageTags = photo.tags.split()
    for tag in imageTags:
        tags.remove_tag(tag, imageKey)
    photo.delete()
        
class UploadHandler(webapp.RequestHandler):
    '''This handler responds to requests on the /upload path. It deals with
    image uploads'''
    
    def check_input(self, imageData):
        '''Check whether we have valid image data'''
        
        try:
            image = images.Image(imageData)
            format = image.format
            width = image.width
            height = image.height
            return True
        except:
            return False
        
    def post(self):
        
        imageData = self.request.get("img")
        valid_input = self.check_input(imageData)
        if valid_input:
            imgCount = db.GqlQuery("SELECT * FROM Photo ORDER BY upload_date DESC").count()
            title = self.request.get("title")
            if not title:
                title = "image%d.jpg" %imgCount
            key = create_photo(title, imageData)
            send_to_storage(imageData, str(key))
            create_thumbnail(imageData, str(key))
            self.redirect('/view/%s' %str(key))
        else:
            self.redirect('/error/')
        
class UpdateHandler(webapp.RequestHandler):
    '''This handler handles incoming requests from the image editor'''
    
    def get(self, values):
        
        user = users.get_current_user()
        key = self.request.get('title')
        photo = get_photo(self, key)

        imageURL =  self.request.get('image').replace("http://", "")
        link = "http://%s" %imageURL
        response = urllib2.urlopen(link)
        imageData = response.read()
        size = len(imageData)
        
        send_to_storage(imageData, key)
        create_thumbnail(imageData, key)
        
        photo.datasize = size
        photo.upload_date = datetime.datetime.now()
        photo.put()
        self.redirect('/view/%s' %key)
        
        
class ThumbHandler(webapp.RequestHandler):
    '''This handler returns thumbnail images'''
    
    def get(self, key):

        photo = get_photo(self, key)
        filename = '/gs/user_images_thumb/%s.jpg' %key
        with files.open(filename, 'r') as f:
            imageData = f.read(photo.datasize)
        self.response.headers['Content-Type'] = 'image/jpeg'
        self.response.out.write(imageData)
            
class ServeHandler(webapp.RequestHandler):
    
    def get(self, key):
    
        photo = get_photo(self, key)
        filename = '/gs/user_images/%s.jpg' %key
        with files.open(filename, 'r') as f:
            imageData = f.read(photo.datasize)
        self.response.headers['Content-Type'] = 'image/jpeg'
        self.response.out.write(imageData)
    
    def post(self, key):
        
        photo = get_photo(self, key)
        bDel = self.request.get("delete")   
        bSave = self.request.get("save")
        bShare = self.request.get("share")
        if bDel and check_owner(photo.ownerID):
            delete_photo(self, key)
            self.redirect('/')
        elif bShare:
            #upload_facebook(key, photo)
            self.redirect('/')
        else:
            filename = '/gs/user_images/%s.jpg' %key
            with files.open(filename, 'r') as f:
                data = f.read(photo.datasize)
            if bSave:
                self.response.headers['Content-Type'] = 'application/force-download'
                self.response.headers['Content-Type'] = 'application/octet-stream'
                self.response.headers['Content-Disposition'] = "attachment; filename=%s" %photo.title
                self.response.out.write(data)
            else:
                self.response.headers['Content-Type'] = 'image/jpeg'
                self.response.out.write(data)